import { ref, onUnmounted } from 'vue'
import SockJS from 'sockjs-client'
import { Client } from '@stomp/stompjs'
import { useUserStore } from '../../auth/stores/user'

// 统一任务消息接口
export interface UnifiedTaskMessage {
  type: string      // 功能模块类型，如"outline", "chapter", "analysis"等
  taskId: string    // 任务唯一标识，如"bookid_outline", "bookid_chapter_num"等
  status: string    // 任务状态
  progress?: number // 任务进度
  message: string   // 消息内容
  timestamp: number // 时间戳
}

// 保持向后兼容的接口
export interface TaskProgress {
  taskId: string
  progress: number
  message: string
  timestamp: number
}

export interface TaskStatus {
  taskId: string
  status: string
  message: string
  timestamp: number
}

export interface TaskCompletion {
  taskId: string
  status: string
  result: any
  timestamp: number
}

export interface TaskFailure {
  taskId: string
  status: string
  message: string
  timestamp: number
}

export class WebSocketService {
  private socket: any = null
  private stompClient: any = null
  private reconnectAttempts = 0
  private maxReconnectAttempts = 5
  private reconnectDelay = 3000
  private subscriptions = new Map<string, Function[]>()
  private messageCallbacks: Map<string, Function[]> = new Map()
  private connectionState = ref<'disconnected' | 'connecting' | 'connected' | 'error'>('disconnected')
  private authCheckInterval: any = null
  private lastConnectionState: boolean | null = null
  
  // 连接URL - 使用统一端点
  private readonly connectUrl = '/ws-unified'
  
  // 打印当前所有回调键
  printAllCallbackKeys() {
    console.log('当前所有注册的回调键:', Array.from(this.messageCallbacks.keys()))
  }

  /**
   * 获取所有消息回调
   */
  getMessageCallbacks(): string[] {
    const callbacks = Array.from(this.messageCallbacks.keys())
    console.log('获取所有消息回调:', callbacks)
    return callbacks
  }

  constructor() {
    // 不再自动连接，等待用户认证成功后手动连接
    console.log('WebSocket服务已创建，等待用户认证后连接')
  }

  private connectionPromise: Promise<void> | null = null

  /**
   * 连接WebSocket
   */
  async connect(): Promise<void> {
    // 检查用户认证状态
    const userStore = useUserStore()
    if (!userStore.isAuthenticated) {
      console.log('用户未认证，不连接WebSocket')
      return Promise.reject(new Error('用户未认证'))
    }

    // 如果已经连接或正在连接，直接返回
    if (this.isConnected() || this.connectionPromise) {
      console.log('WebSocket已连接或正在连接中')
      return this.connectionPromise || Promise.resolve()
    }

    // 设置连接状态为连接中
    this.connectionState.value = 'connecting'
    
    this.connectionPromise = new Promise((resolve, reject) => {
      try {
        // 获取WebSocket基础URL
        const wsBaseUrl = import.meta.env.VITE_WS_BASE_URL || 'http://127.0.0.1:8080'
        // 确保URL不以/结尾，避免SockJS连接问题
        const normalizedBaseUrl = wsBaseUrl.endsWith('/') ? wsBaseUrl.slice(0, -1) : wsBaseUrl
        const wsUrl = `${normalizedBaseUrl}${this.connectUrl}`
        
        console.log('正在连接WebSocket:', wsUrl)
        console.log('注意: 使用SockJS连接，URL应为HTTP协议而非WS协议')
        
        // 获取token用于认证
        const token = userStore.getToken()
        
        // 创建WebSocket连接
        this.socket = new SockJS(wsUrl, null, {
          transports: ['websocket', 'xhr-streaming', 'xhr-polling'],
          timeout: 5000
        })
        this.stompClient = new Client({
          webSocketFactory: () => this.socket,
          debug: (str) => {
            console.log('STOMP调试:', str)
          },
          reconnectDelay: 5000,
          heartbeatIncoming: 4000,
          heartbeatOutgoing: 4000,
          // 添加认证头
          connectHeaders: {
            Authorization: token ? `Bearer ${token}` : ''
          }
        })

        // 连接成功回调
        this.stompClient.onConnect = () => {
          console.log('WebSocket连接成功')
          this.connectionState.value = 'connected'
          this.reconnectAttempts = 0
          this.connectionPromise = null
          
          // 订阅统一任务主题
          this.subscribeToUnifiedTopic()
          
          // 重新订阅所有主题
          this.subscriptions.forEach((callbacks, destination) => {
            callbacks.forEach(callback => {
              this.subscribe(destination, callback)
            })
          })
          
          resolve()
        }

        // 连接错误回调
        this.stompClient.onStompError = (error: any) => {
          console.error('WebSocket连接失败:', error)
          console.error('STOMP错误详情:', error.headers?.message || error.message)
          this.connectionState.value = 'error'
          this.connectionPromise = null
          
          // 检查是否是认证错误
          if (error.headers?.message?.includes('Authentication') || 
              error.headers?.message?.includes('认证失败') ||
              error.message?.includes('Authentication') ||
              error.message?.includes('认证失败')) {
            console.log('WebSocket认证失败，但不触发全局认证错误事件，避免影响其他API请求')
            // 不再触发全局认证错误事件，避免影响其他API请求
            // window.dispatchEvent(new CustomEvent('auth-error'))
            // 不再尝试重连
            return
          }
          
          // 尝试重连
          this.handleReconnect()
          
          reject(error)
        }
        
        // 添加SockJS级别的错误处理
        this.socket.onclose = (event: any) => {
          console.warn('SockJS连接关闭:', {
            code: event.code,
            reason: event.reason,
            wasClean: event.wasClean
          })
          this.connectionState.value = 'disconnected'
          this.connectionPromise = null
          
          // 如果不是正常关闭且未达到最大重试次数，则尝试重连
          if (!event.wasClean && this.reconnectAttempts < this.maxReconnectAttempts) {
            console.log('SockJS异常关闭，尝试重连')
            this.handleReconnect()
          }
        }
        
        // 添加SockJS错误处理
        this.socket.onerror = (error: any) => {
          console.error('SockJS连接错误:', error)
          this.connectionState.value = 'error'
        }

        // 激活连接
        this.stompClient.activate()
      } catch (error) {
        console.error('创建WebSocket连接失败:', error)
        this.connectionState.value = 'error'
        this.connectionPromise = null
        this.handleReconnect()
        reject(error)
      }
    })

    return this.connectionPromise
  }

  /**
   * 重新连接
   */
  reconnect(): void {
    console.log('重新连接WebSocket')
    this.disconnect()
    setTimeout(() => {
      this.connect()
    }, 1000)
  }

  /**
   * 订阅通知
   * @param callback 接收通知的回调函数
   * @returns 取消订阅的函数
   */
  subscribeToNotifications(callback: (notification: any) => void): () => void {
    this.registerTypeCallback('notification', callback);
    
    // 订阅用户个人通知主题
    const subscription = this.subscribe(`/user/queue/notifications`, (message: any) => {
      try {
        const notification = JSON.parse(message.body);
        // 创建一个符合UnifiedTaskMessage接口的通知对象
        const unifiedNotification: UnifiedTaskMessage = {
          type: 'notification',
          taskId: 'notification',
          status: 'notification',
          message: notification.message || notification.content || '',
          timestamp: notification.timestamp || Date.now()
        };
        this.dispatchMessage(unifiedNotification);
      } catch (error) {
        console.error('解析通知消息失败:', error);
      }
    });
    
    // 订阅任务完成通知主题
    const userStore = useUserStore();
    const userId = userStore.userInfo?.id;
    if (userId) {
      const taskCompletionSubscription = this.subscribe(`/topic/user/${userId}/tasks/completion`, (message: any) => {
        try {
          const notification = JSON.parse(message.body);
          // 创建一个符合UnifiedTaskMessage接口的通知对象
          const unifiedNotification: UnifiedTaskMessage = {
            type: 'task_completion',
            taskId: notification.taskId || 'unknown',
            status: notification.status || 'COMPLETED',
            message: notification.message || notification.content || '',
            timestamp: notification.timestamp || Date.now()
          };
          this.dispatchMessage(unifiedNotification);
        } catch (error) {
          console.error('解析任务完成通知消息失败:', error);
        }
      });
      
      // 返回取消订阅函数
      return () => {
        this.unregisterTypeCallback('notification', callback);
        subscription?.unsubscribe();
        taskCompletionSubscription?.unsubscribe();
      };
    }
    
    // 返回取消订阅函数
    return () => {
      this.unregisterTypeCallback('notification', callback);
      subscription?.unsubscribe();
    };
  }

  /**
   * 订阅任务进度更新
   * @param type 任务类型
   * @param taskId 任务ID
   * @param callback 回调函数
   */
  subscribeToTaskProgress(type: string, taskId: string, callback: (message: UnifiedTaskMessage) => void): () => void {
    this.registerTaskCallback(type, taskId, callback)
    
    // 如果已连接，立即订阅
    if (this.isConnected()) {
      this.subscribeToUnifiedTopic()
    }
    
    // 返回取消订阅函数
    return () => {
      this.unregisterTaskCallback(type, taskId, callback)
    }
  }

  /**
   * 订阅任务状态更新
   * @param type 任务类型
   * @param taskId 任务ID
   * @param callback 回调函数
   */
  subscribeToTaskStatus(type: string, taskId: string, callback: (message: UnifiedTaskMessage) => void): () => void {
    this.registerTaskCallback(type, taskId, callback)
    
    // 如果已连接，立即订阅
    if (this.isConnected()) {
      this.subscribeToUnifiedTopic()
    }
    
    // 返回取消订阅函数
    return () => {
      this.unregisterTaskCallback(type, taskId, callback)
    }
  }

  /**
   * 订阅任务完成通知
   * @param type 任务类型
   * @param taskId 任务ID
   * @param callback 回调函数
   */
  subscribeToTaskCompletion(type: string, taskId: string, callback: (message: UnifiedTaskMessage) => void): () => void {
    this.registerTaskCallback(type, taskId, (message: UnifiedTaskMessage) => {
      if (message.status === 'COMPLETED') {
        callback(message)
      }
    })
    
    // 如果已连接，立即订阅
    if (this.isConnected()) {
      this.subscribeToUnifiedTopic()
    }
    
    // 返回取消订阅函数
    return () => {
      this.unregisterTaskCallback(type, taskId, callback)
    }
  }

  /**
   * 订阅任务失败通知
   * @param type 任务类型
   * @param taskId 任务ID
   * @param callback 回调函数
   */
  subscribeToTaskFailure(type: string, taskId: string, callback: (message: UnifiedTaskMessage) => void): () => void {
    this.registerTaskCallback(type, taskId, (message: UnifiedTaskMessage) => {
      if (message.status === 'FAILED') {
        callback(message)
      }
    })
    
    // 如果已连接，立即订阅
    if (this.isConnected()) {
      this.subscribeToUnifiedTopic()
    }
    
    // 返回取消订阅函数
    return () => {
      this.unregisterTaskCallback(type, taskId, callback)
    }
  }

  /**
   * 订阅统一任务主题
   */
  private subscribeToUnifiedTopic() {
    if (!this.stompClient || !this.stompClient.connected) return

    this.stompClient.subscribe('/topic/unified-task', (message: any) => {
      try {
        const unifiedMessage: UnifiedTaskMessage = JSON.parse(message.body)
        console.log('收到统一任务消息:', unifiedMessage)

        // 根据消息类型分发到对应的回调函数
        this.dispatchMessage(unifiedMessage)
      } catch (error) {
        console.error('解析统一任务消息失败:', error)
      }
    })
    
    console.log('已订阅统一任务主题: /topic/unified-task')
    this.subscriptions.set('unified-task', [() => {}])
  }

  /**
   * 公共方法：订阅统一任务消息
   * @param callback 回调函数
   */
  subscribeToUnifiedTask(callback: (message: UnifiedTaskMessage) => void) {
    // 注册回调
    this.registerTypeCallback('unified-task', callback)
    
    // 如果已连接，立即订阅
    if (this.isConnected()) {
      this.subscribeToUnifiedTopic()
    }
    
    // 返回取消订阅函数
    return () => {
      this.unregisterTypeCallback('unified-task', callback)
    }
  }

  /**
   * 分发消息到对应的回调函数
   */
  private dispatchMessage(message: UnifiedTaskMessage) {
    const { type, taskId } = message
    const callbackKey = `${type}_${taskId}`
    
    console.log('分发消息，原始taskId:', taskId, '类型:', type, '组合key:', callbackKey)
    
    // 调用特定任务的回调函数
    let callbacks = this.messageCallbacks.get(callbackKey)
    
    if (callbacks) {
      console.log('找到回调函数，数量:', callbacks.length)
      callbacks.forEach(callback => {
        try {
          callback(message)
        } catch (error) {
          console.error('执行任务消息回调失败:', error)
        }
      })
    } else {
      console.log('未找到匹配的回调函数')
      console.log('当前所有注册的回调键:', Array.from(this.messageCallbacks.keys()))
    }

    // 调用类型的通用回调函数
    const typeCallbacks = this.messageCallbacks.get(type)
    if (typeCallbacks) {
      console.log('找到类型回调函数，数量:', typeCallbacks.length)
      typeCallbacks.forEach(callback => {
        try {
          callback(message)
        } catch (error) {
          console.error('执行类型消息回调失败:', error)
        }
      })
    }
  }

  /**
   * 注册任务消息回调函数
   */
  registerTaskCallback(type: string, key: string, callback: Function) {
    const callbackKey = `${type}_${key}`
    console.log('注册任务回调，key:', callbackKey)
    
    if (!this.messageCallbacks.has(callbackKey)) {
      this.messageCallbacks.set(callbackKey, [])
    }
    
    this.messageCallbacks.get(callbackKey)!.push(callback)
  }

  /**
   * 注册类型消息回调函数
   */
  registerTypeCallback(type: string, callback: Function) {
    console.log('注册类型回调，类型:', type)
    
    if (!this.messageCallbacks.has(type)) {
      this.messageCallbacks.set(type, [])
    }
    
    this.messageCallbacks.get(type)!.push(callback)
  }

  /**
   * 取消注册任务消息回调函数
   */
  unregisterTaskCallback(type: string, key: string, callback: Function) {
    const callbackKey = `${type}_${key}`
    console.log('取消注册任务回调，key:', callbackKey)
    const callbacks = this.messageCallbacks.get(callbackKey)
    
    if (callbacks) {
      const index = callbacks.indexOf(callback)
      if (index > -1) {
        callbacks.splice(index, 1)
      }
      
      if (callbacks.length === 0) {
        this.messageCallbacks.delete(callbackKey)
      }
    }
  }

  /**
   * 取消注册类型消息回调函数
   * @param type 类型
   * @param callback 回调函数
   */
  unregisterTypeCallback(type: string, callback: Function) {
    console.log('取消注册类型回调，类型:', type)
    
    const callbacks = this.messageCallbacks.get(type)
    if (callbacks) {
      const index = callbacks.indexOf(callback)
      if (index > -1) {
        callbacks.splice(index, 1)
        if (callbacks.length === 0) {
          this.messageCallbacks.delete(type)
        }
      }
    }
  }

  /**
   * 清理所有订阅
   */
  clearAllSubscriptions(): void {
    console.log('清理所有订阅')
    this.subscriptions.forEach((callbacks, key) => {
      try {
        callbacks.forEach(callback => {
          if (typeof callback === 'function') {
            callback()
          }
        })
      } catch (error) {
        console.error('取消订阅失败:', key, error)
      }
    })
    this.subscriptions.clear()
  }

  /**
   * 清理所有回调
   */
  clearAllCallbacks(): void {
    console.log('清理所有消息回调')
    this.messageCallbacks.clear()
  }

  /**
   * 清理所有资源
   */
  clearAll(): void {
    console.log('清理所有WebSocket资源')
    this.clearAllSubscriptions()
    this.clearAllCallbacks()
    this.disconnect()
  }

  /**
   * 通用订阅方法
   * @param destination 订阅地址
   * @param callback 回调函数
   */
  private subscribe(destination: string, callback: Function) {
    // 保存回调函数，以便重连时重新订阅
    if (!this.subscriptions.has(destination)) {
      this.subscriptions.set(destination, [])
    }
    this.subscriptions.get(destination)?.push(callback)

    // 如果已连接，立即订阅
    if (this.stompClient && this.stompClient.connected) {
      console.log('正在订阅主题:', destination)
      const subscription = this.stompClient.subscribe(destination, (message: any) => {
        try {
          const data = JSON.parse(message.body)
          callback(data)
        } catch (error) {
          console.error('解析WebSocket消息失败:', error)
        }
      })
      console.log('已订阅主题:', destination)
      return subscription
    }

    return null
  }

  /**
   * 取消订阅
   * @param destination 订阅地址
   * @param callback 回调函数
   */
  unsubscribe(destination: string, callback?: Function) {
    console.log('正在取消订阅主题，目标:', destination)
    if (callback) {
      // 取消特定回调
      const callbacks = this.subscriptions.get(destination)
      if (callbacks) {
        const index = callbacks.indexOf(callback)
        if (index !== -1) {
          callbacks.splice(index, 1)
          console.log('已取消特定回调，目标:', destination)
        }
      }
    } else {
      // 取消所有回调
      this.subscriptions.delete(destination)
      console.log('已取消所有回调，目标:', destination)
    }
  }

  /**
   * 断开连接
   */
  disconnect(): void {
    if (this.stompClient && this.stompClient.connected) {
      this.stompClient.deactivate()
      console.log('WebSocket连接已断开')
    }
    
    if (this.socket) {
      this.socket.close()
      this.socket = null
    }
    
    this.stompClient = null
    this.connectionState.value = 'disconnected'
    this.connectionPromise = null
  }

  /**
   * 清理资源
   */
  cleanup(): void {
    // 清理认证检查定时器
    if (this.authCheckInterval) {
      clearInterval(this.authCheckInterval)
      this.authCheckInterval = null
    }
    
    // 断开连接
    this.disconnect()
    
    // 清理所有订阅
    this.subscriptions.clear()
    this.messageCallbacks.clear()
  }

  /**
   * 处理重连逻辑
   */
  private handleReconnect() {
    if (this.reconnectAttempts < this.maxReconnectAttempts) {
      this.reconnectAttempts++
      console.log(`尝试重连 (${this.reconnectAttempts}/${this.maxReconnectAttempts})，${this.reconnectDelay/1000}秒后重试...`)
      
      setTimeout(() => {
        this.connectionState.value = 'connecting'
        this.connect().catch(error => {
          console.error('重连失败:', error)
        })
      }, this.reconnectDelay)
      
      // 增加重连延迟
      this.reconnectDelay = Math.min(this.reconnectDelay * 1.5, 30000) // 最大30秒
    } else {
      console.error('达到最大重连次数，停止重连')
      this.connectionState.value = 'error'
    }
  }

  /**
   * 获取所有订阅
   */
  getSubscriptions(): string[] {
    const subscriptions = Array.from(this.subscriptions.keys())
    console.log('获取所有订阅:', subscriptions)
    return subscriptions
  }

  /**
   * 检查连接状态
   */
  isConnected(): boolean {
    const connected = this.stompClient?.connected || false
    // 只在连接状态改变时输出日志
    if (this.lastConnectionState !== connected) {
      console.log('检查WebSocket连接状态:', connected)
      this.lastConnectionState = connected
    }
    return connected
  }

  /**
   * 发送消息
   */
  send(destination: string, body: any): void {
    if (!this.isConnected()) {
      console.error('WebSocket未连接，无法发送消息')
      return
    }

    console.log('发送WebSocket消息，目标:', destination, '内容:', body)
    this.stompClient.send(destination, {}, JSON.stringify(body))
  }

  /**
   * 获取连接状态
   */
  getConnectionStatus(): 'disconnected' | 'connecting' | 'connected' | 'error' {
    const status = this.connectionState.value
    console.log('获取WebSocket连接状态:', status)
    return status
  }

  /**
   * 获取Socket
   */
  getSocket(): any {
    console.log('获取Socket:', !!this.socket)
    return this.socket
  }

  /**
   * 获取STOMP客户端
   */
  getStompClient(): any {
    console.log('获取STOMP客户端:', !!this.stompClient)
    return this.stompClient
  }
}

// 创建全局WebSocket服务实例
export const webSocketService = new WebSocketService()

// 普通JavaScript函数，不使用Vue的组合式API
export function useWebSocket() {
  return {
    isConnected: webSocketService.isConnected(),
    error: null,
    // 统一消息处理方法
    registerTaskCallback: (type: string, key: string, callback: Function) => {
      webSocketService.registerTaskCallback(type, key, callback)
    },
    registerTypeCallback: (type: string, callback: Function) => {
      webSocketService.registerTypeCallback(type, callback)
    },
    unregisterTaskCallback: (type: string, key: string, callback: Function) => {
      webSocketService.unregisterTaskCallback(type, key, callback)
    },
    unregisterTypeCallback: (type: string, callback: Function) => {
      webSocketService.unregisterTypeCallback(type, callback)
    },
    // 保持向后兼容的方法
    subscribeToTaskProgress: webSocketService.subscribeToTaskProgress.bind(webSocketService),
    subscribeToTaskStatus: webSocketService.subscribeToTaskStatus.bind(webSocketService),
    subscribeToTaskCompletion: webSocketService.subscribeToTaskCompletion.bind(webSocketService),
    subscribeToTaskFailure: webSocketService.subscribeToTaskFailure.bind(webSocketService),
    unsubscribe: webSocketService.unsubscribe.bind(webSocketService),
    disconnect: webSocketService.disconnect.bind(webSocketService)
  }
}

// Vue组合式函数，用于在组件中使用
export function useWebSocketVue() {
  const isConnected = ref(false)
  const connectionStatus = ref<'disconnected' | 'connecting' | 'connected' | 'error'>('disconnected')
  const error = ref<string | null>(null)

  // 监听连接状态
  const checkConnection = () => {
    isConnected.value = webSocketService.isConnected() || false
    connectionStatus.value = webSocketService.getConnectionStatus()
    
    // 根据连接状态设置错误信息
    if (connectionStatus.value === 'error') {
      error.value = 'WebSocket连接失败，请刷新页面重试'
    } else if (connectionStatus.value === 'disconnected') {
      error.value = 'WebSocket已断开连接'
    } else {
      error.value = null
    }
  }

  // 立即检查一次
  checkConnection()

  // 定期检查连接状态
  const connectionChecker = setInterval(checkConnection, 1000)

  // 组件卸载时清理
  onUnmounted(() => {
    clearInterval(connectionChecker)
  })

  return {
    isConnected,
    connectionStatus,
    error,
    // 统一消息处理方法
    registerTaskCallback: (type: string, key: string, callback: Function) => {
      webSocketService.registerTaskCallback(type, key, callback)
    },
    registerTypeCallback: (type: string, callback: Function) => {
      webSocketService.registerTypeCallback(type, callback)
    },
    unregisterTaskCallback: (type: string, key: string, callback: Function) => {
      webSocketService.unregisterTaskCallback(type, key, callback)
    },
    unregisterTypeCallback: (type: string, callback: Function) => {
      webSocketService.unregisterTypeCallback(type, callback)
    },
    // 保持向后兼容的方法
    subscribeToTaskProgress: webSocketService.subscribeToTaskProgress.bind(webSocketService),
    subscribeToTaskStatus: webSocketService.subscribeToTaskStatus.bind(webSocketService),
    subscribeToTaskCompletion: webSocketService.subscribeToTaskCompletion.bind(webSocketService),
    subscribeToTaskFailure: webSocketService.subscribeToTaskFailure.bind(webSocketService),
    unsubscribe: webSocketService.unsubscribe.bind(webSocketService),
    disconnect: webSocketService.disconnect.bind(webSocketService),
    // 连接方法
    connect: webSocketService.connect.bind(webSocketService)
  }
}